/*
 * Adam Blackwell 
 * ada2358@ccs.neu.edu
 * 
 * Nice to get back to Eclipse :), 
 */

// Coord : An (x,y) representation of an object on a 2d map.
class Coord {
  // Private variables.
  private int x;
  private int y;
  
  // Constructor.
  private Coord(int x, int y) {
    this.x = x;
    this.y = y;
    if (x < 0 || y < 0) {
      throw new IllegalArgumentException("InCoord.create(x,y), " +
      		                             "x and y must both be non-negative numbers");
    }
  }

  // Create : Factory Method, Replaces Constructor.
  // Create : Int Int -> Coord 
  // Coord.create(x,y).xPos()=x
  public static Coord create(int x, int y) {
    return new Coord(x, y);
  }
  
  // XPos : Accessor, Gets the X position or the horizontal offset from the origin.
  // XPos : -> Int
  // Coord.create(x,y).yPos()=y
  public int xPos() {
    return this.x;
  }
  
  // YPos : Accessor, Gets the Y position or the vertical offset from the origin.
  // YPos : -> Int
  // Coord.create(x,y).yPos()=y
  public int yPos() {
    return this.y;
  }

  // Move : Moves this Coord in a functional manner, uses create defined in ADT
  // Note this keeps the function abstract very well.
  // Move : Int Int -> Coord
  // Coord.create(x,y).move(xchange,ychange) = Coord.create(x+xchange,y+ychange)
  public Coord move(int xchange, int ychange) {
    return Coord.create(this.xPos() + xchange, this.yPos() + ychange);
  }
  
  
  // Add : Takes the x and y values from c and moves this Coord by those amounts.
  // Add : Coord -> Coord
  // Coord.create(x,y).add(c)=Coord.create(x+c.xPos(),y+c.yPos())
  public Coord add(Coord c) {
    return this.move(c.xPos(), c.yPos());
    // First Revision:
    // return Coord.create(x + c.xPos(), y + c.yPos());
  }
  
  // WhithIn : Determines if this Coord is with in the square created by two other Coords.
  // WhithIn : Coord Coord -> Boolean
  // Coord.create(x,y).within(c1,c2) = true if c1.xPos() <= x <= c2.xPos() and
  // c1.yPos() <= y <= c2.yPos() = false otherwise.
  public boolean within(Coord c1, Coord c2) {
    return (c1.xPos() <= this.xPos()) && (c2.xPos() >= this.xPos()) && 
           (c1.yPos() <= this.yPos()) && (c2.yPos() >= this.yPos());
  }
  
  // Equals : Checks if two Coords have the same properties.
  // Equals : Coord -> Boolean
  // Coord.create(x,y).equals(c) = true if x = c.xPos() and y = c.yPos() = false otherwise
  public boolean equals(Coord c) {
    return (this.xPos() == c.xPos()) && (this.yPos() == c.yPos());
  }
  
  // Equals : Here to fully implement Equals, when passed a Coord Equals will default to the above method.
  // Equals : Object -> Boolean
  // Coord.create(x,y).equals(obj)=false
  public boolean equals(Object obj) {
    return false;
  }
  
  // HashCode : Creates a Unique Number based on this Coords Elements.
  // HashCode : -> Int
  // Coord.create(x,y).hashCode() = (x+y) * (x+y+1) / 2+y
  public int hashCode() {
    return (((this.xPos() + this.yPos()) * 
             (this.xPos() + this.yPos() + 1)) / 2)
            + this.yPos();
  }
  
  // ToString : Creates a String Representation of this Coord.
  // ToString : -> String
  // Coord.create(x,y).toString()="("+x+","+y+")"
  public String toString() {
    return "(" + x + "," + y + ")";
  }
}
/*
 * 2a) 
 * public int distance(Coord); 
 * 
 * 2b) 
 * Coord.create(x,y).distance(Coord.create(a,b)) = 
 * The Square Root of y-b squared plus x-a squared?
 * /sqrt{(y-b)^2+(x-a)^2} 
 * 
 * public double distance(Coord c){ 
 *   return Math.sqrt(Math.pow((c.yPos() - this.yPos()), 2) + 
 *                    Math.pow((c.xPos() - this.xPos()), 2)); 
 *   } 
 *   
 * 3a) 
 * Coord.origin().xPos() = 0
 * Coord.origin().yPos() = 0 
 * xPos and yPos become contants no longer determined when the method is called.
 * 
 * Coord.origin().move(xchange,ychange) = Coord.create(xchange,ychange) 
 * Move can always start at 0,0, making it more like create.
 * 
 * Coord.origin().add(c) = Coord.create(c.xPos(),c.yPos()) 
 * ... etc.
 * 
 * 3b)
 * The Change you could chose to make would be to define origin with create.
 * Coord.origin() = Coord.create(0,0)
 */
